home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / graphics 3d / ravecontextsample / source / qd3d_support.c < prev   
Encoding:
C/C++ Source or Header  |  2000-06-23  |  23.4 KB  |  863 lines

  1. /****************************/
  2. /*       QD3D SUPPORT.C        */
  3. /* By Brian Greenstone      */
  4. /****************************/
  5.  
  6.  
  7. /****************************/
  8. /*    EXTERNALS             */
  9. /****************************/
  10. #include <NumberFormatting.h>
  11. #include <Resources.h>
  12.  
  13. #include <QD3D.h>
  14. #include <QD3DGroup.h>
  15. #include <QD3DLight.h>
  16. #include <QD3DTransform.h>
  17. #include <QD3DStorage.h>
  18. #include <QD3DMath.h>
  19. #include <QD3DErrors.h>
  20. #include <Rave.h>
  21. #include <ImageCompression.h>
  22.  
  23. #include <timer.h>
  24. #include "myglobals.h"
  25. #include "misc.h"
  26. #include "qd3d_support.h"
  27.  
  28. extern    EventRecord            gTheEvent;
  29. extern    WindowPtr            gModelWindow;
  30.  
  31. /****************************/
  32. /*    PROTOTYPES            */
  33. /****************************/
  34.  
  35. static void CreateDrawContext(QD3DViewDefType *viewDefPtr);
  36. static void SetStyles(QD3DStyleDefType *styleDefPtr);
  37. static void CreateCamera(QD3DCameraDefType *cameraDefPtr);
  38. static void CreateLights(QD3DLightDefType *lightDefPtr);
  39. static void CreateView(QD3DSetupInputType *setupDefPtr);
  40. static void CreateTexturePixmap(PicHandle pict,unsigned long mapSizeX,
  41.                              unsigned long mapSizeY, TQ3StoragePixmap *bMap);
  42. static void GWorldToBMap(GWorldPtr pGWorld, TQ3StoragePixmap *bMap);
  43. static void DrawPICTIntoPixmap(PicHandle pict,unsigned long width, unsigned long height, TQ3StoragePixmap *bMap);
  44. static TQ3SurfaceShaderObject    QD3D_PICTToTexture(PicHandle picture);
  45. static TQ3SurfaceShaderObject    QD3D_GWorldToTexture(GWorldPtr theGWorld);
  46.  
  47.  
  48. /****************************/
  49. /*    CONSTANTS             */
  50. /****************************/
  51.  
  52.  
  53. /*********************/
  54. /*    VARIABLES      */
  55. /*********************/
  56.  
  57. static TQ3CameraObject            gQD3D_CameraObject;
  58. static TQ3GroupObject            gQD3D_LightGroup;
  59. static TQ3ViewObject            gQD3D_ViewObject;
  60. static TQ3DrawContextObject        gQD3D_DrawContext;
  61. static TQ3RendererObject        gQD3D_RendererObject;
  62. static TQ3ShaderObject            gQD3D_ShaderObject;
  63. static    TQ3StyleObject            gQD3D_BackfacingStyle;
  64. static    TQ3StyleObject            gQD3D_FillStyle;
  65. static    TQ3StyleObject            gQD3D_InterpolationStyle;
  66.  
  67. float    gFramesPerSecond = DEFAULT_FPS;                // this is used to maintain a constant timing velocity as frame rates differ
  68.  
  69.  
  70.  
  71.  
  72. //=======================================================================================================
  73. //=============================== VIEW WINDOW SETUP STUFF ===============================================
  74. //=======================================================================================================
  75.  
  76.  
  77. /************** SETUP QD3D WINDOW *******************/
  78.  
  79. void QD3D_SetupWindow(QD3DSetupInputType *setupDefPtr, QD3DSetupOutputType *outputPtr)
  80. {
  81.     CreateView(setupDefPtr);
  82.     Q3InteractiveRenderer_SetDoubleBufferBypass(gQD3D_RendererObject,kQ3True);        // let hardware go fast    
  83.     CreateCamera(&setupDefPtr->camera);                                        // create new CAMERA object
  84.     CreateLights(&setupDefPtr->lights);
  85.     SetStyles(&setupDefPtr->styles);    
  86.     
  87.  
  88.                 /* DISPOSE OF EXTRA REFERENCES */
  89.                 
  90.     Q3Object_Dispose(gQD3D_RendererObject);                // (is contained w/in gQD3D_ViewObject)
  91.  
  92.     
  93.                 /* PASS BACK INFO */
  94.                 
  95.     outputPtr->viewObject = gQD3D_ViewObject;
  96.     outputPtr->interpolationStyle = gQD3D_InterpolationStyle;
  97.     outputPtr->fillStyle = gQD3D_FillStyle;
  98.     outputPtr->backfacingStyle = gQD3D_BackfacingStyle;
  99.     outputPtr->shaderObject = gQD3D_ShaderObject;
  100.     outputPtr->cameraObject = gQD3D_CameraObject;
  101.     outputPtr->lightGroup = gQD3D_LightGroup;
  102.     outputPtr->drawContext = gQD3D_DrawContext;
  103.     outputPtr->window = setupDefPtr->view.displayWindow;        // remember which window
  104.     outputPtr->paneClip = setupDefPtr->view.paneClip;
  105. }
  106.  
  107.  
  108. /***************** QD3D_DisposeWindowSetup ***********************/
  109. //
  110. // Disposes of all data created by QD3D_SetupWindow
  111. //
  112.  
  113. void QD3D_DisposeWindowSetup(QD3DSetupOutputType *data)
  114. {
  115.     Q3Object_Dispose(data->viewObject);
  116.     Q3Object_Dispose(data->interpolationStyle);
  117.     Q3Object_Dispose(data->backfacingStyle);
  118.     Q3Object_Dispose(data->fillStyle);
  119.     Q3Object_Dispose(data->cameraObject);
  120.     Q3Object_Dispose(data->lightGroup);
  121.     Q3Object_Dispose(data->drawContext);
  122.     Q3Object_Dispose(data->shaderObject);
  123. }
  124.  
  125.  
  126. /******************* CREATE GAME VIEW *************************/
  127.  
  128. static void CreateView(QD3DSetupInputType *setupDefPtr)
  129. {
  130. TQ3Status    myErr;
  131. unsigned long    hints;
  132.  
  133.                 /* CREATE NEW VIEW OBJECT */
  134.                 
  135.     gQD3D_ViewObject = Q3View_New();
  136.     if (gQD3D_ViewObject == nil)
  137.         DoFatalAlert("\pQ3View_New failed!");
  138.  
  139.  
  140.             /* CREATE & SET DRAW CONTEXT */
  141.     
  142.     CreateDrawContext(&setupDefPtr->view);                                 // init draw context
  143.     
  144.     myErr = Q3View_SetDrawContext(gQD3D_ViewObject, gQD3D_DrawContext);            // assign context to view
  145.     if (myErr == kQ3Failure)
  146.         DoFatalAlert("\pQ3View_SetDrawContext Failed!");
  147.  
  148.  
  149.  
  150.             /* CREATE & SET RENDERER */
  151.  
  152.     gQD3D_RendererObject = Q3Renderer_NewFromType(setupDefPtr->view.rendererType);    // create new RENDERER object
  153.     if (gQD3D_RendererObject == nil)
  154.     {
  155.         QD3D_ShowError("\pQ3Renderer_NewFromType Failed!", true);
  156.         CleanQuit();
  157.     }
  158.  
  159.     myErr = Q3View_SetRenderer(gQD3D_ViewObject, gQD3D_RendererObject);                // assign renderer to view
  160.     if (myErr == kQ3Failure)
  161.         DoFatalAlert("\pQ3View_SetRenderer Failed!");
  162.  
  163.         /* SET RENDERER FEATURES */
  164.         
  165.     Q3InteractiveRenderer_GetRAVEContextHints(gQD3D_RendererObject, &hints);
  166.     hints &= ~kQAContext_NoZBuffer;                 // Z buffer is on 
  167.     hints &= ~kQAContext_DeepZ;                     // Z buffer is not deep, ergo it's shallow 
  168.     hints |= kQAContext_NoDither;                     // No Dither 
  169.     Q3InteractiveRenderer_SetRAVEContextHints(gQD3D_RendererObject, hints);    
  170.     
  171.     Q3InteractiveRenderer_SetRAVETextureFilter(gQD3D_RendererObject,kQATextureFilter_Mid);    // fast texturing
  172.     Q3InteractiveRenderer_SetDoubleBufferBypass(gQD3D_RendererObject,kQ3True);
  173. }
  174.  
  175.  
  176. /**************** CREATE SKELETON DRAW CONTEXT *********************/
  177.  
  178. static void CreateDrawContext(QD3DViewDefType *viewDefPtr)
  179. {
  180. TQ3DrawContextData        drawContexData;
  181. TQ3MacDrawContextData    myMacDrawContextData;
  182. Rect                    r;
  183.  
  184.     r = viewDefPtr->displayWindow->portRect;
  185.  
  186.  
  187.             /* FILL IN DRAW CONTEXT DATA */
  188.  
  189.     drawContexData.clearImageMethod = kQ3ClearMethodWithColor;                // how to clear
  190.     drawContexData.clearImageColor = viewDefPtr->clearColor;                // color to clear to
  191.     drawContexData.pane.min.x = r.left+viewDefPtr->paneClip.left;            // set bounds?
  192.     drawContexData.pane.max.x = r.right-viewDefPtr->paneClip.right;
  193.     drawContexData.pane.min.y = r.top+viewDefPtr->paneClip.top;
  194.     drawContexData.pane.max.y = r.bottom-viewDefPtr->paneClip.bottom;
  195.     drawContexData.paneState = kQ3True;                                        // use bounds?
  196.     drawContexData.maskState = kQ3False;                                    // no mask
  197.     drawContexData.doubleBufferState = kQ3True;                                // double buffering
  198.  
  199.     myMacDrawContextData.drawContextData = drawContexData;                    // set MAC specifics
  200.     myMacDrawContextData.window = (CWindowPtr)viewDefPtr->displayWindow;    // assign window to draw to
  201.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;                        // use standard QD libraries (no GX crap!)
  202.     myMacDrawContextData.viewPort = nil;                                    // (for GX only)
  203.     myMacDrawContextData.grafPort = (CWindowPtr)viewDefPtr->displayWindow;    // assign grafport
  204.  
  205.  
  206.             /* CREATE DRAW CONTEXT */
  207.  
  208.     gQD3D_DrawContext = Q3MacDrawContext_New(&myMacDrawContextData);
  209.     if (gQD3D_DrawContext == nil)
  210.         DoFatalAlert("\pQ3MacDrawContext_New Failed!");
  211. }
  212.  
  213.  
  214. /**************** SET STYLES ****************/
  215. //
  216. // Creates style objects which define how the scene is to be rendered.
  217. // It also sets the shader object.
  218. //
  219.  
  220. static void SetStyles(QD3DStyleDefType *styleDefPtr)
  221. {
  222.  
  223.  
  224.                 /* SET INTERPOLATION (FOR SHADING) */
  225.                     
  226.     gQD3D_InterpolationStyle = Q3InterpolationStyle_New(styleDefPtr->interpolation);
  227.     if (gQD3D_InterpolationStyle == nil)
  228.         DoFatalAlert("\pQ3InterpolationStyle_New Failed!");
  229.  
  230.                     /* SET BACKFACING */
  231.  
  232.     gQD3D_BackfacingStyle = Q3BackfacingStyle_New(styleDefPtr->backfacing);
  233.     if (gQD3D_BackfacingStyle == nil )
  234.         DoFatalAlert("\pQ3BackfacingStyle_New Failed!");
  235.  
  236.  
  237.                 /* SET POLYGON FILL STYLE */
  238.                         
  239.     gQD3D_FillStyle = Q3FillStyle_New(styleDefPtr->fill);
  240.     if ( gQD3D_FillStyle == nil )
  241.         DoFatalAlert("\p Q3FillStyle_New Failed!");
  242.  
  243.  
  244.                     /* SET THE SHADER TO USE */
  245.  
  246.     switch(styleDefPtr->illuminationType)
  247.     {
  248.         case    kQ3IlluminationTypePhong:
  249.                 gQD3D_ShaderObject = Q3PhongIllumination_New();
  250.                 if ( gQD3D_ShaderObject == nil )
  251.                     DoFatalAlert("\p Q3PhongIllumination_New Failed!");
  252.                 break;
  253.                 
  254.         case    kQ3IlluminationTypeLambert:
  255.                 gQD3D_ShaderObject = Q3LambertIllumination_New();
  256.                 if ( gQD3D_ShaderObject == nil )
  257.                     DoFatalAlert("\p Q3LambertIllumination_New Failed!");
  258.                 break;
  259.                 
  260.         case    kQ3IlluminationTypeNULL:
  261.                 gQD3D_ShaderObject = Q3NULLIllumination_New();
  262.                 if ( gQD3D_ShaderObject == nil )
  263.                     DoFatalAlert("\p Q3NullIllumination_New Failed!");
  264.                 break;
  265.     }    
  266. }
  267.  
  268.  
  269.  
  270. /****************** CREATE CAMERA *********************/
  271.  
  272. static void CreateCamera(QD3DCameraDefType *cameraDefPtr)
  273. {
  274. TQ3CameraData                    myCameraData;
  275. TQ3ViewAngleAspectCameraData    myViewAngleCameraData;
  276. TQ3Area                            pane;
  277. TQ3Status                        status;
  278. TQ3Status    myErr;
  279.  
  280.     status = Q3DrawContext_GetPane(gQD3D_DrawContext,&pane);                // get window pane info
  281.     if (status == kQ3Failure)
  282.         DoFatalAlert("\pQ3DrawContext_GetPane Failed!");
  283.  
  284.  
  285.                 /* FILL IN CAMERA DATA */
  286.                 
  287.     myCameraData.placement.cameraLocation = cameraDefPtr->from;            // set camera coords
  288.     myCameraData.placement.pointOfInterest = cameraDefPtr->to;            // set target coords
  289.     myCameraData.placement.upVector = cameraDefPtr->up;                    // set a vector that's "up"
  290.     myCameraData.range.hither = cameraDefPtr->hither;                    // set frontmost Z dist
  291.     myCameraData.range.yon = cameraDefPtr->yon;                            // set farthest Z dist
  292.     myCameraData.viewPort.origin.x = -1.0;                                // set view origins?
  293.     myCameraData.viewPort.origin.y = 1.0;
  294.     myCameraData.viewPort.width = 2.0;
  295.     myCameraData.viewPort.height = 2.0;
  296.  
  297.     myViewAngleCameraData.cameraData = myCameraData;
  298.     myViewAngleCameraData.fov = cameraDefPtr->fov;                        // larger = more fisheyed
  299.     myViewAngleCameraData.aspectRatioXToY =
  300.                 (pane.max.x-pane.min.x)/(pane.max.y-pane.min.y);
  301.  
  302.     gQD3D_CameraObject = Q3ViewAngleAspectCamera_New(&myViewAngleCameraData);     // create new camera
  303.     if (gQD3D_CameraObject == nil)
  304.         DoFatalAlert("\pQ3ViewAngleAspectCamera_New failed!");
  305.         
  306.     myErr = Q3View_SetCamera(gQD3D_ViewObject, gQD3D_CameraObject);        // assign camera to view
  307.     if (myErr == kQ3Failure)
  308.         DoFatalAlert("\pQ3View_SetCamera Failed!");
  309.  
  310. }
  311.  
  312.  
  313. /********************* CREATE LIGHTS ************************/
  314.  
  315. static void CreateLights(QD3DLightDefType *lightDefPtr)
  316. {
  317. TQ3GroupPosition        myGroupPosition;
  318. TQ3LightData            myLightData;
  319. TQ3DirectionalLightData    myDirectionalLightData;
  320. TQ3LightObject            myLight;
  321. short                    i;
  322. TQ3Status    myErr;
  323.  
  324.  
  325.             /* CREATE NEW LIGHT GROUP */
  326.             
  327.     gQD3D_LightGroup = Q3LightGroup_New();                        // make new light group
  328.     if ( gQD3D_LightGroup == nil )
  329.         DoFatalAlert("\p Q3LightGroup_New Failed!");
  330.  
  331.  
  332.     myLightData.isOn = kQ3True;                                    // light is ON
  333.     
  334.             /************************/
  335.             /* CREATE AMBIENT LIGHT */
  336.             /************************/
  337.  
  338.     if (lightDefPtr->ambientBrightness != 0)                        // see if ambient exists
  339.     {
  340.         myLightData.color = lightDefPtr->ambientColor;                // set color of light
  341.         myLightData.brightness = lightDefPtr->ambientBrightness;    // set brightness value
  342.         myLight = Q3AmbientLight_New(&myLightData);                    // make it
  343.         if ( myLight == nil )
  344.             DoFatalAlert("\pQ3AmbientLight_New Failed!");
  345.  
  346.         myGroupPosition = Q3Group_AddObject(gQD3D_LightGroup, myLight);    // add to group
  347.         if ( myGroupPosition == 0 )
  348.             DoFatalAlert("\p Q3Group_AddObject Failed!");
  349.  
  350.         Q3Object_Dispose(myLight);                                    // dispose of light
  351.  
  352.     }
  353.  
  354.             /**********************/
  355.             /* CREATE FILL LIGHTS */
  356.             /**********************/
  357.             
  358.     for (i=0; i < lightDefPtr->numFillLights; i++)
  359.     {        
  360.         myLightData.color = lightDefPtr->fillColor[i];                        // set color of light
  361.         myLightData.brightness = lightDefPtr->fillBrightness[i];            // set brightness
  362.         myDirectionalLightData.lightData = myLightData;                        // refer to general light info
  363.         myDirectionalLightData.castsShadows = kQ3False;                        // no shadows
  364.         myDirectionalLightData.direction =  lightDefPtr->fillDirection[i];    // set fill vector
  365.         myLight = Q3DirectionalLight_New(&myDirectionalLightData);            // make it
  366.         if ( myLight == nil )
  367.             DoFatalAlert("\p Q3DirectionalLight_New Failed!");
  368.  
  369.         myGroupPosition = Q3Group_AddObject(gQD3D_LightGroup, myLight);        // add to group
  370.         if ( myGroupPosition == 0 )
  371.             DoFatalAlert("\p Q3Group_AddObject Failed!");
  372.  
  373.         Q3Object_Dispose(myLight);                                            // dispose of light
  374.     }
  375.     
  376.             /* ASSIGN LIGHT GROUP TO VIEW */
  377.             
  378.     myErr = Q3View_SetLightGroup(gQD3D_ViewObject, gQD3D_LightGroup);        // assign light group to view
  379.     if (myErr == kQ3Failure)
  380.         DoFatalAlert("\pQ3View_SetLightGroup Failed!");        
  381.  
  382. }
  383.  
  384. /******************** QD3D CHANGE DRAW SIZE *********************/
  385. //
  386. // Changes size of stuff to fit new window size.
  387. //
  388.  
  389. void QD3D_ChangeDrawSize(QD3DSetupOutputType *setupInfo)
  390. {
  391. Rect            r;
  392. TQ3Area            pane;
  393. TQ3ViewAngleAspectCameraData    cameraData;
  394.  
  395.             /* CHANGE DRAW CONTEXT PANE SIZE */
  396.             
  397.     r = setupInfo->window->portRect;                            // get size of window
  398.     pane.min.x = r.left+setupInfo->paneClip.left;                                        // set pane size
  399.     pane.max.x = r.right-setupInfo->paneClip.right;
  400.     pane.min.y = r.top+setupInfo->paneClip.top;
  401.     pane.max.y = r.bottom-setupInfo->paneClip.bottom;
  402.     Q3DrawContext_SetPane(setupInfo->drawContext,&pane);        // update pane in draw context
  403.  
  404.  
  405.                 /* CHANGE CAMERA ASPECT RATIO */
  406.                 
  407.     Q3ViewAngleAspectCamera_GetData(setupInfo->cameraObject,&cameraData);            // get camera data
  408.     cameraData.aspectRatioXToY = (pane.max.x-pane.min.x)/(pane.max.y-pane.min.y);    // set new aspect ratio
  409.     Q3ViewAngleAspectCamera_SetData(setupInfo->cameraObject,&cameraData);            // set new camera data
  410. }
  411.  
  412.  
  413. /******************* QD3D DRAW SCENE *********************/
  414.  
  415. void QD3D_DrawScene(QD3DSetupOutputType *setupInfo, void (*drawRoutine)(QD3DSetupOutputType *))
  416. {
  417. TQ3Status                myStatus;
  418. TQ3ViewStatus            myViewStatus;
  419.  
  420.             /* START RENDERING */
  421.  
  422.     myStatus = Q3View_StartRendering(setupInfo->viewObject);            
  423.     if ( myStatus == kQ3Failure )
  424.     {
  425.         DoFatalAlert("\p Q3View_StartRendering Failed!");
  426.     }
  427.     
  428.             /***************/
  429.             /* RENDER LOOP */
  430.             /***************/
  431.     do
  432.     {
  433.                 /* DRAW STYLES */
  434.                 
  435.         myStatus = Q3Style_Submit(setupInfo->interpolationStyle,setupInfo->viewObject);
  436.         if ( myStatus == kQ3Failure )
  437.             DoFatalAlert("\p Q3Style_Submit Failed!");
  438.             
  439.         myStatus = Q3Style_Submit(setupInfo->backfacingStyle,setupInfo->viewObject);
  440.         if ( myStatus == kQ3Failure )
  441.             DoFatalAlert("\p Q3Style_Submit Failed!");
  442.             
  443.         myStatus = Q3Style_Submit(setupInfo->fillStyle, setupInfo->viewObject);
  444.         if ( myStatus == kQ3Failure )
  445.             DoFatalAlert("\p Q3Style_Submit Failed!");
  446.  
  447.         myStatus = Q3Shader_Submit(setupInfo->shaderObject, setupInfo->viewObject);
  448.         if ( myStatus == kQ3Failure )
  449.             DoFatalAlert("\p Q3Shader_Submit Failed!");
  450.  
  451.  
  452.             /* CALL INPUT DRAW FUNCTION */
  453.  
  454.         drawRoutine(setupInfo);
  455.  
  456.         myViewStatus = Q3View_EndRendering(setupInfo->viewObject);
  457.         
  458.     } while ( myViewStatus == kQ3ViewStatusRetraverse );
  459.     
  460. }
  461.  
  462.  
  463. //=======================================================================================================
  464. //=============================== MISC ==================================================================
  465. //=======================================================================================================
  466.  
  467. /************** QD3D CALC FRAMES PER SECOND *****************/
  468.  
  469. float    QD3D_CalcFramesPerSecond(void)
  470. {
  471. UnsignedWide    wide;
  472. unsigned long    now;
  473. static    unsigned long then = 0;
  474.  
  475.     Microseconds(&wide);
  476.     now = wide.lo;
  477.     if (then != 0)
  478.     {
  479.         gFramesPerSecond = (float)1000000.0/(float)(now-then);
  480.         if (gFramesPerSecond < DEFAULT_FPS)            // (avoid divide by 0's later)
  481.             gFramesPerSecond = DEFAULT_FPS;
  482.     
  483.     }
  484.     else
  485.         gFramesPerSecond = DEFAULT_FPS;
  486.         
  487.     then = now;                                // remember time    
  488.     
  489.     return(gFramesPerSecond);
  490. }
  491.  
  492.  
  493. #pragma mark ========== error stuff ===========
  494.  
  495.  
  496. /******************* QD3D: SHOW ERROR *************************/
  497. //
  498. // Returns true if Error, false if just a warning.
  499. //
  500.  
  501. Boolean QD3D_ShowError(Str255 errString, Boolean showWarnings)
  502. {
  503. TQ3Error    err;
  504. TQ3Warning    warning;
  505. Str255        numStr;
  506.  
  507.         /* DO ERRORS */
  508.         
  509.     err = Q3Error_Get(nil);
  510.     if (err != 0)
  511.     {
  512.         DoAlert(errString);
  513.         switch(err)
  514.         {
  515.             case    kQ3ErrorViewNotStarted:
  516.                     DoFatalAlert("\pError:kQ3ErrorViewNotStarted");
  517.                     break;
  518.                     
  519.             case    kQ3ErrorOutOfMemory:
  520.                     DoFatalAlert("\pError:kQ3ErrorOutOfMemory");
  521.                     break;
  522.                     
  523.             default:
  524.                     ShowSystemErr(err);
  525.         }
  526.         return(true);
  527.     }
  528.     
  529.         /* DO WARNINGS */
  530.     else
  531.     {
  532.         if (!showWarnings)
  533.             return(false);
  534.         
  535.         DoAlert(errString);
  536.         warning = Q3Warning_Get(nil);
  537.         switch(warning)
  538.         {
  539.             case    kQ3WarningFunctionalityNotSupported:
  540.                     DoAlert("\pWarning: kQ3WarningFunctionalityNotSupported");
  541.                     break;
  542.                     
  543.             default:
  544.                     NumToString(err, numStr);
  545.                     DoAlert (numStr);
  546.         }
  547.         return(false);
  548.     }
  549.     
  550.     
  551. }
  552.  
  553.  
  554. /************ QD3D: SHOW RECENT ERROR *******************/
  555.  
  556. void QD3D_ShowRecentError(void)
  557. {
  558. TQ3Error    q3Err;
  559. Str255        s;
  560.     
  561.     q3Err = Q3Error_Get(nil);
  562.     if (q3Err == kQ3ErrorOutOfMemory)
  563.         QD3D_DoMemoryError();
  564.     else
  565.     if (q3Err == kQ3ErrorMacintoshError)
  566.         DoFatalAlert("\pkQ3ErrorMacintoshError");
  567.     else
  568.     if (q3Err != 0)
  569.     {
  570.         NumToString(q3Err,s);
  571.         DoFatalAlert(s);
  572.     }
  573. }
  574.  
  575. /***************** QD3D: DO MEMORY ERROR **********************/
  576.  
  577. void QD3D_DoMemoryError(void)
  578. {
  579.     InitCursor();
  580.     NoteAlert(129,nil);
  581.     CleanQuit();
  582. }
  583.  
  584.  
  585. #pragma mark =========== textures =================
  586.  
  587. /**************** QD3D GET TEXTURE MAP ***********************/
  588. //
  589. // Loads a PICT resource and returns a shader object which is
  590. // based on the PICT converted to a texture map.
  591. //
  592. // INPUT: textureRezID = resource ID of texture PICT to get.
  593. //            myFSSpec != nil if want to load PICT from file instead
  594. //
  595. // OUTPUT: TQ3ShaderObject = shader object for texture map.
  596. //
  597.  
  598. TQ3SurfaceShaderObject    QD3D_GetTextureMap(long    textureRezID, FSSpec *myFSSpec)
  599. {
  600. PicHandle            picture;
  601. TQ3SurfaceShaderObject        shader;
  602. long                pictSize,headerSize;
  603. OSErr                iErr;
  604. short                fRefNum;
  605. char                pictHeader[512];
  606.  
  607.     if (myFSSpec == nil)
  608.     {
  609.                     /* LOAD PICT REZ */
  610.         
  611.         picture = GetPicture (textureRezID);
  612.         if (picture == nil)
  613.             DoFatalAlert("\pUnable to load texture PICT resource");
  614.     }
  615.     else
  616.     {
  617.                 /* LOAD PICT FROM FILE */
  618.     
  619.         iErr = FSpOpenDF(myFSSpec,fsCurPerm,&fRefNum);
  620.         if (iErr)
  621.             DoFatalAlert("\pError reading PICT file!");
  622.  
  623.         if    (GetEOF(fRefNum,&pictSize) != noErr)        // get size of file        
  624.             DoFatalAlert("\pError reading PICT file!");
  625.                 
  626.         headerSize = 512;                    // check the header                    
  627.         if (FSRead(fRefNum,&headerSize,pictHeader) != noErr)
  628.             DoFatalAlert("\pError reading PICT file!");
  629.  
  630.         if ((pictSize -= 512) <= 0)
  631.             DoFatalAlert("\pError reading PICT file!");
  632.             
  633.         if ((picture = (PicHandle)NewHandle(pictSize)) == nil)
  634.             DoFatalAlert("\pNot enough memory to read PICT file!");
  635.         HLock((Handle)picture);
  636.             
  637.         if (FSRead(fRefNum,&pictSize,*picture) != noErr)
  638.             DoFatalAlert("\pError reading PICT file!");
  639.             
  640.         FSClose(fRefNum);        
  641.     }
  642.     
  643.     
  644.     shader = QD3D_PICTToTexture(picture);
  645.         
  646.     if (myFSSpec == nil)
  647.         ReleaseResource ((Handle) picture);
  648.     else
  649.         DisposeHandle((Handle)picture);
  650.  
  651.     return(shader);    
  652. }
  653.  
  654.  
  655. /**************** QD3D PICT TO TEXTURE ***********************/
  656. //
  657. //
  658. // INPUT: picture = handle to PICT.
  659. //
  660. // OUTPUT: TQ3ShaderObject = shader object for texture map.
  661. //
  662.  
  663. static TQ3SurfaceShaderObject    QD3D_PICTToTexture(PicHandle picture)
  664. {
  665. TQ3StoragePixmap     pixmap;
  666. TQ3TextureObject    texture;
  667. TQ3SurfaceShaderObject        shader;
  668.  
  669.             /* MAKE INTO STORAGE PIXMAP */
  670.     
  671.     pixmap.image = nil;
  672.     CreateTexturePixmap (picture,
  673.                 (**picture).picFrame.right  - (**picture).picFrame.left,
  674.                 (**picture).picFrame.bottom - (**picture).picFrame.top,
  675.                 &pixmap);
  676.     
  677.  
  678.             /* MAKE NEW PIXMAP TEXTURE */
  679.             
  680.     texture = Q3PixmapTexture_New (&pixmap);
  681.     if (texture == nil)
  682.         DoFatalAlert("\pError calling Q3PixmapTexture_New!");
  683.         
  684.     shader = Q3TextureShader_New (texture);
  685.     if (shader == nil)
  686.         DoFatalAlert("\pError calling Q3TextureShader_New!");
  687.  
  688.     Q3Object_Dispose (texture);
  689.     Q3Object_Dispose (pixmap.image);            // disposes of extra reference to storage obj from CreateTexturePixmap
  690.  
  691.     return(shader);    
  692. }
  693.  
  694.  
  695. /**************** QD3D GWORLD TO TEXTURE ***********************/
  696. //
  697. // INPUT: picture = handle to PICT.
  698. //
  699. // OUTPUT: TQ3ShaderObject = shader object for texture map.
  700. //
  701.  
  702. static TQ3SurfaceShaderObject    QD3D_GWorldToTexture(GWorldPtr theGWorld)
  703. {
  704. TQ3StoragePixmap             pixmap;
  705. TQ3TextureObject            texture;
  706. TQ3SurfaceShaderObject        shader;
  707.  
  708.  
  709.     GWorldToBMap(theGWorld,&pixmap);
  710.  
  711.  
  712.             /* MAKE NEW PIXMAP TEXTURE */
  713.             
  714.     texture = Q3PixmapTexture_New (&pixmap);
  715.     if (texture == nil)
  716.         DoFatalAlert("\pError calling Q3PixmapTexture_New!");
  717.  
  718.     shader = Q3TextureShader_New(texture);
  719.     if (shader == nil)
  720.         DoFatalAlert("\pError calling Q3TextureShader_New!");
  721.  
  722.     Q3Object_Dispose (texture);
  723.     Q3Object_Dispose (pixmap.image);            // possible memory leak if dont call this?!?!
  724.  
  725.     return(shader);    
  726. }
  727.  
  728.  
  729.  
  730.  
  731. /******************** CREATE TEXTURE PIXMAP ********************/
  732.  
  733. static void CreateTexturePixmap(PicHandle pict,unsigned long mapSizeX,
  734.                              unsigned long mapSizeY, TQ3StoragePixmap *bMap)
  735. {
  736.     bMap->image = NULL;
  737.     
  738.     if (mapSizeY > 512)
  739.         mapSizeY = 512;
  740.     if (mapSizeX > 512)
  741.         mapSizeX = 512;
  742.     
  743.     DrawPICTIntoPixmap (pict, mapSizeX, mapSizeY, bMap);
  744. }
  745.  
  746.  
  747.  
  748. /******************** DRAW PICT INTO PIXMAP ********************/
  749. //
  750. // OUTPUT: bMap = new bitmap holding texture image
  751. //
  752.  
  753. static void DrawPICTIntoPixmap(PicHandle pict,unsigned long width, unsigned long height, TQ3StoragePixmap *bMap)
  754. {
  755.     #define    k80K        (80000)
  756.  
  757. Rect                     rectGW;
  758. GWorldPtr                 pGWorld;
  759. PixMapHandle             hPixMap;
  760. OSErr                    myErr;
  761. GDHandle                oldGD;
  762. GWorldPtr                oldGW;
  763. long                    bytesNeeded;
  764.  
  765.     GetGWorld(&oldGW, &oldGD);                                        // save current port
  766.  
  767.  
  768.                 /* CREATE A GWORLD TO DRAW INTO */
  769.  
  770.     SetRect(&rectGW, 0, 0, width, height);                        // set dimensions
  771.     bytesNeeded = (width * height * 4) + k80K;
  772.     if (bytesNeeded < MaxBlock())
  773.         myErr = NewGWorld(&pGWorld, 16, &rectGW, 0, 0, 0L);            // make gworld
  774.     else
  775.         myErr = -43;
  776.     if (myErr)
  777.         DoFatalAlert("\pError making texture GWorld!");
  778.     
  779.     hPixMap = GetGWorldPixMap(pGWorld);                            // calc addr & rowbytes
  780.  
  781.  
  782.             /* DRAW PICTURE INTO GWORLD */
  783.             
  784.     SetGWorld(pGWorld, nil);    
  785.     LockPixels(hPixMap);
  786.     EraseRect(&rectGW);
  787.     DrawPicture(pict, &rectGW);
  788.  
  789.  
  790.             /* MAKE A PIXMAP FROM GWORLD */
  791.             
  792.     GWorldToBMap(pGWorld,bMap);
  793.     
  794.     SetGWorld (oldGW, oldGD);
  795.     UnlockPixels (hPixMap);
  796.     DisposeGWorld (pGWorld);
  797. }
  798.  
  799.  
  800.  
  801. /******************** GWORLD TO BMAP ********************/
  802. //
  803. // Creates a TQ3StoragePixmap from an existing GWorld
  804. //
  805. // NOTE: Assumes that GWorld is 16bit!!!!
  806. //
  807. // OUTPUT: bMap = new bitmap holding texture image
  808. //
  809.  
  810. static void GWorldToBMap(GWorldPtr pGWorld, TQ3StoragePixmap *bMap)
  811. {
  812. unsigned long             pictMapAddr;
  813. PixMapHandle             hPixMap;
  814. unsigned long             pictRowBytes;
  815. long                    width, height;
  816. TQ3Status                status;
  817.     
  818.     hPixMap = GetGWorldPixMap(pGWorld);                                // calc addr & rowbytes
  819.     
  820.     if ((**hPixMap).pixelSize != 16)                                    // verify bitdepth
  821.         DoFatalAlert("\pGworlds must be 16bit when converting to textures!");
  822.     
  823.     pictMapAddr = (unsigned long )GetPixBaseAddr(hPixMap);
  824.     pictRowBytes = (unsigned long)(**hPixMap).rowBytes & 0x3fff;
  825.     width = ((**hPixMap).bounds.right - (**hPixMap).bounds.left);
  826.     height = ((**hPixMap).bounds.bottom - (**hPixMap).bounds.top);
  827.  
  828.  
  829.                 /* SET MORE PIXELMAP INFO */
  830.  
  831.     if (bMap->image != NULL)
  832.     {
  833.         DoAlert("\pReplacing PixelMap : (remove this Alert if I want this");
  834.         status = Q3MemoryStorage_Set (bMap->image, (unsigned char *) pictMapAddr,
  835.                              pictRowBytes * height);
  836.         if (status == kQ3Failure)
  837.             DoFatalAlert("\pQ3MemoryStorage_Set Failed!");
  838.     }
  839.     else
  840.     {
  841.         bMap->image = Q3MemoryStorage_New ((unsigned char *) pictMapAddr, pictRowBytes * height);
  842.         if (bMap->image == nil)
  843.             DoFatalAlert("\pQ3MemoryStorage_New Failed!");
  844.     }
  845.  
  846.  
  847.  
  848.     bMap->width     = width;
  849.     bMap->height    = height;
  850.     bMap->rowBytes     = pictRowBytes;
  851.     bMap->pixelSize = 16;
  852.     bMap->pixelType    = kQ3PixelTypeRGB16;
  853.     bMap->bitOrder    = kQ3EndianBig;
  854.     bMap->byteOrder    = kQ3EndianBig;
  855.     
  856. }
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.